package com.yycx.module.admin.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yycx.common.constants.CommonConstants;
import com.yycx.common.enums.StateEnum;
import com.yycx.common.exception.OpenAlertException;
import com.yycx.common.mybatis.base.service.impl.BaseServiceImpl;
import com.yycx.common.base.entity.EntityMap;
import com.yycx.common.mybatis.model.ResultBody;
import com.yycx.common.mybatis.query.CriteriaDelete;
import com.yycx.common.mybatis.query.CriteriaQuery;
import com.yycx.common.mybatis.query.CriteriaSave;
import com.yycx.common.mybatis.query.CriteriaUpdate;
import com.yycx.common.security.OpenHelper;
import com.yycx.common.utils.ApiAssert;
import com.yycx.common.base.utils.FlymeUtils;
import com.yycx.common.utils.StringUtils;
import com.yycx.module.admin.client.constants.BaseConstants;
import com.yycx.module.admin.client.entity.BaseRole;
import com.yycx.module.admin.client.entity.BaseRoleUser;
import com.yycx.module.admin.client.entity.BaseUser;
import com.yycx.module.admin.provider.mapper.BaseRoleMapper;
import com.yycx.module.admin.provider.mapper.BaseRoleUserMapper;
import com.yycx.module.admin.provider.service.BaseAuthorityService;
import com.yycx.module.admin.provider.service.BaseRoleService;
import com.yycx.module.admin.provider.service.BaseUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Optional;


/**
 * @author zyf
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class BaseRoleServiceImpl extends BaseServiceImpl<BaseRoleMapper, BaseRole> implements BaseRoleService {
    @Resource
    private BaseRoleMapper baseRoleMapper;
    @Resource
    private BaseRoleUserMapper baseRoleUserMapper;

    @Resource
    private BaseAuthorityService baseAuthorityService;
    @Resource
    private BaseUserService baseUserService;


    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public ResultBody beforePageList(CriteriaQuery<BaseRole> cq, BaseRole baseRole, EntityMap requestMap) {
        BaseRole query = cq.getEntity(BaseRole.class);
        if (FlymeUtils.isNotEmpty(query)) {
            cq.lambda()

                    .eq(FlymeUtils.isNotEmpty(query.getRoleId()), BaseRole::getRoleId, query.getRoleId())
                    .like(FlymeUtils.isNotEmpty(query.getRoleName()), BaseRole::getRoleName, query.getRoleName())
                    .eq(FlymeUtils.isNotEmpty(query.getCompanyId()), BaseRole::getCompanyId, query.getCompanyId())
                    .like(FlymeUtils.isNotEmpty(query.getRoleCode()), BaseRole::getRoleCode, query.getRoleCode());
            cq.likeRight(FlymeUtils.isNotEmpty(query.getRoleCode()), "roleCode", query.getRoleCode()).likeRight(FlymeUtils.isNotEmpty(query.getRoleName()), "roleName", query.getRoleName());
        }
        cq.ne("roleCode",CommonConstants.ROOT);
        cq.orderByDesc("createTime");
        return super.beforePageList(cq, baseRole, requestMap);
    }

    /**
     * 查询列表
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<BaseRole> findAllList() {
        List<BaseRole> list = baseRoleMapper.selectList(new QueryWrapper<>());
        return list;
    }

    /**
     * 查询列表
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<BaseRole> findByCompanyId(Long companyId) {
        CriteriaQuery cq = new CriteriaQuery(BaseRole.class);
        cq.eq("companyId", companyId);
        cq.eq("status", CommonConstants.ENABLED);
        return baseRoleMapper.selectList(cq);
    }

    /**
     * 查询列表
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public List<BaseRole> selectByType(String roleType) {
        CriteriaQuery<BaseRole> cq = new CriteriaQuery(BaseRole.class);
        cq.eq(true, "roleType", roleType);
        List<BaseRole> list = baseRoleMapper.selectList(cq);
        return list;
    }

    /**
     * 获取角色信息
     *
     * @param roleId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public BaseRole getRole(Serializable roleId) {
        return baseRoleMapper.selectById(roleId);
    }


    @Override
    public ResultBody beforeAdd(CriteriaSave cs, BaseRole role, EntityMap extra) {
        ApiAssert.isFalse(String.format("%s编码已存在!", role.getRoleCode()), isExist(role.getRoleCode()));
        role.setStatus(Optional.ofNullable(role.getStatus()).orElse(BaseConstants.ENABLED));
        role.setIsPersist(Optional.ofNullable(role.getIsPersist()).orElse(BaseConstants.DISABLED));
        Integer superAdmin = OpenHelper.getUser().getSuperAdmin();
        if (CommonConstants.INT_0.equals(superAdmin)) {
            Long organizationId = OpenHelper.getOrganizationId();
            if (FlymeUtils.isNotEmpty(organizationId)) {
                role.setOrganizationId(organizationId);
            }
        }
        return ResultBody.ok();
    }


    /**
     * 更新角色
     *
     * @param role 角色
     * @return
     */
    @Override
    public BaseRole updateRole(BaseRole role) {
        BaseRole updated = getRole(role.getRoleId());
        ApiAssert.isEmpty("角色不存在!", updated);
        if (!updated.getRoleCode().equals(role.getRoleCode())) {
            // 和原来不一致重新检查唯一性
            if (isExist(role.getRoleCode())) {
                throw new OpenAlertException(String.format("%s编码已存在!", role.getRoleCode()));
            }
        }
        baseRoleMapper.updateById(role);
        return role;
    }


    @Override
    public ResultBody beforeEdit(CriteriaUpdate<BaseRole> cu, BaseRole baseRole, EntityMap extra) {
        BaseRole role = cu.getEntity(BaseRole.class);
        BaseRole updated = getRole(role.getRoleId());
        ApiAssert.isNotEmpty("角色不存在!", updated);
        return super.beforeEdit(cu, baseRole, extra);
    }

    /**
     * 删除角色
     *
     * @param params 角色
     * @return
     */
    @Override
    public void removeRole(Map params) {
        CriteriaDelete cd = new CriteriaDelete(params, BaseRole.class);
        Serializable[] ids = cd.getIds();
        ApiAssert.isNotEmpty("参数不正确", ids);
        Serializable id = ids[0];
        BaseRole role = getRole(id);
        ApiAssert.isFalse("保留数据,不允许删除", role != null && role.getIsPersist().equals(BaseConstants.ENABLED));
        Long roleId=role.getRoleId();
        //删除角色下面用户
        removeRoleUsers(roleId);
        //删除角色已分配的权限
        baseAuthorityService.removeAuthorityRole(roleId);
        baseDelete(cd);
    }

    /**
     * 设置状态
     *
     * @param roleId
     * @return
     */
    @Override
    public ResultBody setStatus(Long roleId) {
        ResultBody resultBody = new ResultBody();
        BaseRole role = baseRoleMapper.selectById(roleId);
        Integer stateEnum = role.getStatus();
        CriteriaUpdate cu = new CriteriaUpdate();
        cu.eq("roleId", roleId);
        if (stateEnum.equals(StateEnum.ENABLE.getCode())) {
            cu.set(true, "status", StateEnum.DISABLE.getCode());
            resultBody.setMsg(StateEnum.DISABLE.getName() + "成功").data(false);
        } else {
            cu.set(true, "status", StateEnum.ENABLE.getCode());
            resultBody.setMsg(StateEnum.ENABLE.getName() + "成功").data(true);
        }
        update(cu);
        return resultBody;

    }

    /**
     * 检测角色编码是否存在
     *
     * @param roleCode
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public Boolean isExist(String roleCode) {
        if (StringUtils.isBlank(roleCode)) {
            throw new OpenAlertException("roleCode不能为空!");
        }
        QueryWrapper<BaseRole> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseRole::getRoleCode, roleCode);
        return baseRoleMapper.selectCount(queryWrapper) > 0;
    }

    /**
     * 用户添加角色
     *
     * @param userId
     * @param roles
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public void saveUserRoles(Long userId, String... roles) {
        if (userId == null || roles == null) {
            return;
        }
        BaseUser user = baseUserService.getUserById(userId);
        if (user == null) {
            return;
        }
        if (CommonConstants.ROOT.equals(user.getUserName())) {
            throw new OpenAlertException("默认用户无需分配!");
        }
        // 先清空,在添加
        removeUserRoles(userId);
        if (roles.length > 0) {
            for (String roleId : roles) {
                BaseRoleUser roleUser = new BaseRoleUser();
                roleUser.setUserId(userId);
                roleUser.setRoleId(Long.parseLong(roleId));
                baseRoleUserMapper.insert(roleUser);
            }
        }
    }

    @Override
    public BaseRole getRoleByRoleCode(String roleCode) {
        CriteriaQuery cq = new CriteriaQuery(BaseRole.class);
        cq.eq(true, "roleCode", roleCode);
        return getOne(cq);
    }


    /**
     * 角色添加成员
     *
     * @param roleId
     * @param userIds
     */
    @Override
    public void saveRoleUsers(Long roleId, String... userIds) {
        if (roleId == null || userIds == null) {
            return;
        }
        // 先清空,在添加
        removeRoleUsers(roleId);
        if (userIds.length > 0) {
            for (String userId : userIds) {
                BaseRoleUser roleUser = new BaseRoleUser();
                roleUser.setUserId(Long.parseLong(userId));
                roleUser.setRoleId(roleId);
                baseRoleUserMapper.insert(roleUser);
            }
            // 批量保存
        }
    }

    /**
     * 查询角色成员
     *
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<BaseRoleUser> findRoleUsers(Long roleId) {
        QueryWrapper<BaseRoleUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseRoleUser::getRoleId, roleId);
        return baseRoleUserMapper.selectList(queryWrapper);
    }

    /**
     * 获取角色所有授权组员数量
     *
     * @param roleId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public Long getCountByRole(Serializable roleId) {
        QueryWrapper<BaseRoleUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseRoleUser::getRoleId, roleId);
        Long result = baseRoleUserMapper.selectCount(queryWrapper);
        return result;
    }

    /**
     * 获取组员角色数量
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public Long getCountByUser(Long userId) {
        QueryWrapper<BaseRoleUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseRoleUser::getUserId, userId);
        Long result = baseRoleUserMapper.selectCount(queryWrapper);
        return result;
    }

    /**
     * 移除角色所有组员
     *
     * @param roleId
     * @return
     */
    @Override
    public void removeRoleUsers(Long roleId) {
        QueryWrapper<BaseRoleUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseRoleUser::getRoleId, roleId);
        baseRoleUserMapper.delete(queryWrapper);
    }

    /**
     * 移除组员的所有角色
     *
     * @param userId
     * @return
     */
    @Override
    public void removeUserRoles(Serializable userId) {
        QueryWrapper<BaseRoleUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseRoleUser::getUserId, userId);
        baseRoleUserMapper.delete(queryWrapper);
    }

    /**
     * 移除组员的所有角色
     *
     * @param userId
     * @return
     */
    @Override
    public void removeUserRoles(Serializable[] userIds) {
        QueryWrapper<BaseRoleUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().in(BaseRoleUser::getUserId, userIds);
        baseRoleUserMapper.delete(queryWrapper);
    }

    /**
     * 检测是否存在
     *
     * @param userId
     * @param roleId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Boolean isExist(Long userId, Long roleId) {
        QueryWrapper<BaseRoleUser> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().eq(BaseRoleUser::getRoleId, roleId);
        queryWrapper.lambda().eq(BaseRoleUser::getUserId, userId);
        baseRoleUserMapper.delete(queryWrapper);
        Long result = baseRoleUserMapper.selectCount(queryWrapper);
        return result > 0;
    }


    /**
     * 获取组员角色
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<BaseRole> getUserRoles(Long userId) {
        List<BaseRole> roles = baseRoleUserMapper.selectRoleUserList(userId);
        return roles;
    }

    /**
     * 获取用户角色编码
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<String> selectRoleCodesByUserId(Long userId) {
        return baseRoleUserMapper.selectRoleCodesByUserId(userId);
    }

    /**
     * 获取用户角色名称
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<String> selectRoleNamesByUserId(Long userId) {
        return baseRoleUserMapper.selectRoleNamesByUserId(userId);
    }


    @Override
    public List<BaseRole> getRoleByFlowableGroupQueryImpl(Map params) {
        return this.baseMapper.getRolesByGroupQueryImpl(params);
    }

    @Override
    public ResultBody getAuthRoleList(Long userId, Long organizationId,Integer roleType) {
        BaseUser user = baseUserService.getUserById(userId);
        Long companyId = user.getCompanyId();
        CriteriaQuery cq = new CriteriaQuery(BaseRole.class);
        cq.select(BaseRole.class, "roleId", "roleName");
        cq.eq(BaseRole.class, "status", CommonConstants.ENABLED);
        //cq.eq("organizationId", organizationId);
        //cq.eq("companyId", companyId);
        cq.eq("roleType", roleType);
        List<EntityMap> roleList = selectEntityMap(cq);
        List<Long> roleIds = getRoleIds(userId);
        if (FlymeUtils.isNotEmpty(roleList)) {
            for (EntityMap entityMap : roleList) {
                Long roleId = entityMap.getLong("roleId");
                if (roleIds.contains(roleId)) {
                    entityMap.put("checked", true);
                } else {
                    entityMap.put("checked", false);
                }
            }
        }
        EntityMap map = new EntityMap();
        map.put("roleList", roleList);
        map.put("roleIds", roleIds);
        return ResultBody.ok(map);
    }

    /**
     * 获取用户角色ID列表
     *
     * @param userId
     * @return
     */
    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public List<Long> getRoleIds(Long userId) {
        return baseRoleUserMapper.selectRoleUserIdList(userId);
    }

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public Long getRoleId(Long userId) {
        List<Long> roleIds = getRoleIds(userId);
        if (FlymeUtils.isNotEmpty(roleIds)) {
            return roleIds.get(0);
        }
        return null;
    }


}
